page.tsx 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. "use client";
  2. /* eslint-disable @next/next/no-img-element */
  3. import { claimActivityReward } from "@/api/activity";
  4. import { UserVipInfo } from "@/api/user";
  5. import GlobalNotify from "@/components/ModalPopup/GlobalNotifyModal";
  6. import { BoxListCom } from "@/components/ModalPopup/SignInModal";
  7. import { useSignStore } from "@/stores/useSignStore";
  8. import { formatAmount } from "@/utils";
  9. import { server } from "@/utils/client";
  10. import { Toast } from "antd-mobile";
  11. import BigNumber from "bignumber.js";
  12. import { useTranslations } from "next-intl";
  13. import { useSearchParams } from "next/navigation";
  14. import { FC, useEffect, useMemo, useState } from "react";
  15. const getVipApi = async () => {
  16. return server
  17. .request<UserVipInfo>({
  18. url: "/v1/api/user/user_vip_info",
  19. method: "POST",
  20. })
  21. .then((res) => {
  22. if (res.code === 200) return res.data;
  23. });
  24. };
  25. const SignIn: FC = () => {
  26. const searchParams = useSearchParams();
  27. const activity_id = Number(searchParams.get("activity_id"));
  28. const t = useTranslations("signInPage");
  29. const tCode = useTranslations();
  30. const [vipInfo, setVipInfo] = useState<UserVipInfo | null>(null);
  31. const [visible, setVisible] = useState(false);
  32. const [amount, setAmount] = useState({});
  33. useEffect(() => {
  34. getVipInfo();
  35. }, []);
  36. const getVipInfo = async () => {
  37. const vipInfoRes = await getVipApi();
  38. if (vipInfoRes) {
  39. setVipInfo(vipInfoRes);
  40. }
  41. };
  42. const { getSignData, signData } = useSignStore((state) => ({
  43. signData: state.signData,
  44. getSignData: state.getSignData,
  45. }));
  46. useEffect(() => {
  47. getSignData({ activity_id });
  48. }, []);
  49. const curData = useMemo(() => {
  50. if (!signData || !signData.list || signData.cur_num == undefined) return null;
  51. return signData.list[signData.cur_num];
  52. }, [signData]);
  53. const doClaim = async () => {
  54. if (!curData) return null;
  55. try {
  56. const res = await claimActivityReward({
  57. activity_id,
  58. id: curData.id as number,
  59. });
  60. if (res.code === 200 && res?.data?.code === 1) {
  61. getSignData({ activity_id });
  62. if (res?.data?.reward) {
  63. const amountObj: any = {};
  64. res?.data?.reward.forEach((item: any) => {
  65. amountObj[`coin_${item.coin_type}`] = formatAmount(item.amount);
  66. });
  67. //extra_reward
  68. res?.data?.reward.forEach((item: any) => {
  69. amountObj[`coin_${item.coin_type}`] = formatAmount(
  70. new BigNumber(amountObj[`coin_${item.coin_type}`] || 0)
  71. .plus(item.amount)
  72. .toString()
  73. );
  74. });
  75. setAmount(amountObj);
  76. }
  77. setVisible(true);
  78. } else {
  79. throw new Error(tCode(`code.400`));
  80. }
  81. } catch (error: any) {
  82. if (error) {
  83. Toast.show({
  84. content: error.message || error.toString(),
  85. maskClickable: false,
  86. });
  87. }
  88. }
  89. };
  90. return (
  91. <>
  92. <div className="relative h-[100%] w-[100%]">
  93. {/* 主题图片及背景 */}
  94. <div className="relative h-[3.1863rem]">
  95. <img
  96. src="/signDetails/themeBg.png"
  97. alt=""
  98. className="absolute h-[100%] w-[100%]"
  99. />
  100. <div className="relative top-[-0.3363rem] z-50 flex h-[3.0591rem] justify-center">
  101. <img src="/signDetails/theme.png" alt="" className="h-[100%]" />
  102. </div>
  103. <div className="absolute bottom-[0.2136rem] z-50 h-[.3636rem] w-[100%]">
  104. <img src="/signDetails/vip_bg.png" alt="" className="h-[100%] w-[100%]" />
  105. <div className="absolute top-0 h-[100%] w-[100%] px-[0.25rem] text-[white]">
  106. <img
  107. src="/signDetails/vip.png"
  108. alt=""
  109. className="absolute top-[10%] h-[80%]"
  110. />
  111. <div className="relative left-[10%] h-[100%]">
  112. <p className="h-[50%] text-[0.12rem] font-bold leading-[0.2rem]">
  113. VIP {vipInfo?.vip_level || 0}
  114. </p>
  115. <p className="h-[50%] text-[0.1rem] font-bold leading-[0.12rem]">
  116. quanto maior o nível VlP, mais abundantes s?o as recompensas
  117. </p>
  118. </div>
  119. </div>
  120. </div>
  121. </div>
  122. {/* 活动背景 */}
  123. <div className="absolute top-[2.9727rem] w-[100%]">
  124. {/* 右上角文本 */}
  125. <div className="absolute right-[0.1rem] top-0 z-50 h-[0.32rem] w-[20%] text-center text-[0.11rem] font-bold text-[white]">
  126. <p className={"h-[0.16rem]"}>
  127. {signData?.cur_num ? signData?.cur_num + 1 : 0}
  128. </p>
  129. <p className={"h-[0.16rem] text-[yellow]"}>
  130. Day {signData?.list?.length || 0}
  131. </p>
  132. </div>
  133. <img
  134. src="/signDetails/bg3.png"
  135. alt=""
  136. className="z-1 absolute h-[100%] w-[100%]"
  137. />
  138. {/* 免费盒子 */}
  139. <div className="mt-[0.4227rem]">
  140. <BoxListCom type="page" />
  141. </div>
  142. {/* 充值盒子 */}
  143. {/* <div className="h-[1.3273rem]">
  144. <PayBoxList type="page" />
  145. </div> */}
  146. {/* 签到按钮 */}
  147. <div
  148. className={"relative mt-[0.25rem] flex h-[.6045rem] justify-center"}
  149. onClick={doClaim}
  150. >
  151. <img src="/sign/button.png" className={"h-[100%]"} alt="" />
  152. <span className="absolute text-[0.16rem] font-bold leading-[0.375rem] text-[white]">
  153. Sign-in
  154. </span>
  155. </div>
  156. {/* 活动描述文本背景 */}
  157. <div className="relative flex h-[4.4rem] justify-center">
  158. <div className="relative h-[100%]">
  159. <img src="/signDetails/bg2.png" className={"h-[100%]"} alt="" />
  160. <div className="absolute top-0 h-[100%] w-[100%]">
  161. {/* title标题 */}
  162. <div className="h-[0.425rem] text-center text-[.18rem] font-bold leading-[0.425rem] text-[white]">
  163. <p>Activity dedscription</p>
  164. </div>
  165. {/* 描述内容 */}
  166. <div className="h-[3.3455rem] w-[100%] px-[0.15rem] py-[0.2091rem]">
  167. <ul
  168. className={
  169. "break-word list-decimal pl-[.2455rem] pr-[.1rem] pt-0 text-[.14rem] leading-[.23rem] text-[white]"
  170. }
  171. >
  172. <li>{t("desc1")}</li>
  173. <li>{t("desc2")}</li>
  174. <li>{t("desc3")}</li>
  175. <li>{t("desc4")}</li>
  176. <li>{t("desc5")}</li>
  177. <li>{t("desc6")}</li>
  178. </ul>
  179. </div>
  180. </div>
  181. </div>
  182. </div>
  183. </div>
  184. <GlobalNotify
  185. amount={amount}
  186. visible={visible}
  187. onChange={() => setVisible(false)}
  188. deraction={5000}
  189. ></GlobalNotify>
  190. </div>
  191. </>
  192. );
  193. };
  194. export default SignIn;